package com.example.template.interceptor;

import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.template.common.constant.TokenConstant;
import com.example.template.common.exception.GlobalException;
import com.example.template.service.PermissionService;
import com.example.template.utils.JwtUtil;
import com.example.template.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @className: LoginInterceptor
 * @description: 登录拦截器
 * @author: Kuangkeli
 * @date: 2024/01/19 15:54
 **/
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private RedisUtil redisUtil;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("登录拦截器被调用");
        //从请求头中拿到token及客户端类型
        String jwt = request.getHeader("token");
        String clientType = request.getHeader("client_type");
        System.out.println("请求头携带"+clientType);
        if (clientType == null || clientType.isEmpty()) {
            clientType = TokenConstant.CLIENT_TYPE_WEB;
        }
        //获取请求方法
        String method = request.getMethod();
        // 查询验证token
        //这里特别坑，开启跨域之后，对于自定义header，第一次http请求为options嗅探，此时所有自定义header都会为null空指针，
        //第二次发送请求才为get/post，此时如果header为空的话，会自动转化为字符串“null”，注意这里的null是字符串不是null
        if (!"OPTIONS".equals(method)) {
            if (jwt != null && !jwt.isEmpty() && !"null".equals(jwt)) {
                try {
                    //检查JWT是否正确签名 密钥是否匹配
                    DecodedJWT decodedJWT = jwtUtil.verify(jwt);
                    //从JWT的有效载荷中取出token 在redis中根据token查找用户信息 如果存在则放行
                    System.out.println(jwtUtil.getTokenInfo(jwt));
                    if (jwtUtil.checkToken(jwt,clientType)){
                        //token校验成功之后，更新token的超时时间
                        redisUtil.expire(jwtUtil.getTokenInfo(jwt).get("token"), TokenConstant.TOKEN_EXPIRE_TIME);
                        //token校验成功后，将userid存储到request中，后续拦截器和控制器可以直接获取到userid
                        request.setAttribute("userId", jwtUtil.getTokenInfo(jwt).get("userId"));
                        return true;
                    }
                }catch (SignatureVerificationException e){
                    throw new GlobalException("无效签名");
                }catch (TokenExpiredException e){
                    throw new GlobalException("身份认证已过期，请重新登录");
                }catch (AlgorithmMismatchException e){
                    throw new GlobalException("算法不一致");
                }catch (Exception e){
                    throw new GlobalException("token无效");
                }
            }
        }
        throw new GlobalException("请求异常");
    }

}
